package com.clementheliou.cheliou.business.technical.security.authentication.model.builder;

import java.awt.Dimension;
import java.util.ArrayList;
import java.util.Collection;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.util.Assert;

import com.clementheliou.cheliou.business.technical.security.authentication.model.AuthenticationDetails;
import com.clementheliou.cheliou.dal.model.member.enumeration.MemberLocale;
import com.clementheliou.cheliou.util.builder.ObjectBuilder;

/**
 * Builder used to get {@link AuthenticationDetails} instances for test purpose. It must only be
 * used through one of its static factory methods.
 * 
 * @author Clément HELIOU (clement.heliou@gmail.com)
 * @see {@link AuthenticationDetails};
 * @see {@link ObjectBuilder}.
 * @since 1.0
 */
public class AuthenticationDetailsBuilder extends ObjectBuilder<AuthenticationDetails> {

	/**
	 * Private default constructor.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @since 1.0
	 */
	private AuthenticationDetailsBuilder() {
		super();
	}

	/**
	 * Static factory method used to get a builder instance for a {@link AuthenticationDetails}
	 * object that must not be persistent. It's mostly used in tests not having a real data access.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @return the builder instance to be used.
	 * @since 1.0
	 */
	public static AuthenticationDetailsBuilder withNoDependencies() {
		return new AuthenticationDetailsBuilder();
	}

	/**
	 * Creates a default {@link AuthenticationDetails} mock that should never be persisted.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @return the builder instance after this action.
	 * @since 1.0
	 */
	public AuthenticationDetailsBuilder createDefaultAuthenticationDetailsMock() {
		setInstance(createInstance());
		return this;
	}

	/**
	 * Overrides the instance authorities with the given value.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @param authorities the authorities to be set.
	 * @return the builder instance after this action.
	 * @since 1.0
	 */
	public AuthenticationDetailsBuilder overridingAuthorities(final Collection<GrantedAuthority> authorities) {
		Assert.notNull(getObject(), "An instance must be built at this time.");
		getObject().setAuthorities(authorities);
		return this;
	}

	/**
	 * Overrides the instance first name with the given value.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @param firstName the first name to be set.
	 * @return the builder instance after this action.
	 * @since 1.0
	 */
	public AuthenticationDetailsBuilder overridingFirstName(final String firstName) {
		Assert.notNull(getObject(), "An instance must be built at this time.");
		getObject().setFirstName(firstName);
		return this;
	}

	/**
	 * Overrides the instance member locale with the given value.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @param memberLocale the member locale to be set.
	 * @return the builder instance after this action.
	 * @since 1.0
	 */
	public AuthenticationDetailsBuilder overridingMemberLocale(final MemberLocale memberLocale) {
		Assert.notNull(getObject(), "An instance must be built at this time.");
		getObject().setMemberLocale(memberLocale);
		return this;
	}

	/**
	 * Overrides the instance name with the given value.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @param name the name to be set.
	 * @return the builnder instance after this action.
	 * @since 1.0
	 */
	public AuthenticationDetailsBuilder overridingName(final String name) {
		Assert.notNull(getObject(), "An instance must be built at this time.");
		getObject().setName(name);
		return this;
	}

	/**
	 * Creates an {@link AuthenticationDetails} instance with default values. These ones have a
	 * functional sense.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @return the built instance.
	 * @since 1.0
	 */
	private AuthenticationDetails createInstance() {
		final AuthenticationDetails defaultInstance = new AuthenticationDetails();

		defaultInstance.setAccountNonExpired(true);
		defaultInstance.setAccountNonLocked(true);
		defaultInstance.setAuthorities(new ArrayList<GrantedAuthority>());
		defaultInstance.setCredentialsNonExpired(true);
		defaultInstance.setEnabled(true);
		defaultInstance.setFirstName("Steven");
		defaultInstance.setMemberId(12);
		defaultInstance.setMemberLocale(MemberLocale.FRANCAIS);
		defaultInstance.setName("Spielberg");
		defaultInstance.setPassword("password");
		defaultInstance.setScreenSize(new Dimension(1920, 1200));
		defaultInstance.setUsername("steven.spielberg@free.fr");

		return defaultInstance;
	}
}
